using SharpDX;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace Engine.Graphics
{
    public class RenderText : IRenderableObject
    {
        #region Private Fields

        private static SpriteTextRenderer.SharpDX.TextBlockRenderer myTextBlockRenderer;

        private static List<RenderText> TextToRender = new List<RenderText>();

        /// <summary>
        /// 3d-font for text on screen
        /// </summary>
        private SharpDX.DirectWrite.TextFormat direct3dFont;

        private Graphic engine;
        private string message;
        private int posX;
        private int posY;
        private bool queneForRendering = false;
        private SpriteTextRenderer.SharpDX.SpriteRenderer Sprite;
        private SharpDX.Color4 textColor;

        #endregion Private Fields

        #region Public Constructors

        /// <summary>
        /// Initializes a new instance of the RenderText class.
        /// </summary>
        /// <param name="direct3dDevice">This is the 3D Device</param>
        public RenderText(Graphic engine)
        {
            message = string.Empty;
            this.engine = engine;
            if (RenderText.myTextBlockRenderer == null)
                RenderText.myTextBlockRenderer = new SpriteTextRenderer.SharpDX.TextBlockRenderer(
                    engine.SpriteRenderer,
                    "LUCIDA CONSOLE",
                    SharpDX.DirectWrite.FontWeight.Normal,
                    SharpDX.DirectWrite.FontStyle.Normal,
                    SharpDX.DirectWrite.FontStretch.Normal,
                    12);

            //Console.WriteLine("Render Text ist im Moment noch rausgenommen");
            //return;

            //SharpDX.Direct3D11.Device direct3dDevice = engine.Device;// debugInfo;
            //SharpDX.DXGI.SwapChain swapChain = engine.swapChain;
            //var backBuffer = swapChain.GetBackBuffer<SharpDX.DXGI.Surface>(0);

            //// Create the DirectWrite factory object.
            //SharpDX.Direct2D1.Factory d21factory = new SharpDX.Direct2D1.Factory(SharpDX.Direct2D1.FactoryType.SingleThreaded, SharpDX.Direct2D1.DebugLevel.None);
            //SharpDX.DirectWrite.Factory fontFactory = new SharpDX.DirectWrite.Factory();
            ////SharpDX.Direct2D1.D2D1.CreateFactory( d21factory,)
            //SharpDX.DirectWrite.TextRenderer tr =
            //    //// Creates a Testfont for the DirectX 3d Window
            //    // this.textSprite = new Sprite(direct3dDevice);
            //this.direct3dFont = new SharpDX.DirectWrite.TextFormat(fontFactory, "Arial", 12);
            //this.message = "no Message is set!";
            //this.posX = 0;
            //this.posY = 0;
            //this.textColor = new SharpDX.ColorBGRA(0, 0, 255, 0);
            ////SharpDX.Direct2D1.RenderTarget renderTarget = new SharpDX.Direct2D1.RenderTarget(fontFactory, SharpDX.DXGI.Surface.FromSwapChain(swapChain,0), new SharpDX.Direct2D1.RenderTargetProperties(  SharpDX.Direct2D1.RenderTargetType.Default, new  SharpDX.Direct2D1.PixelFormat( SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Ignore),96,96, SharpDX.Direct2D1.RenderTargetUsage.None, SharpDX.Direct2D1.FeatureLevel.Level_DEFAULT));
            //// https://www.indiedev.de/forum/viewtopic.php?t=1255&p=10146
        }

        #endregion Public Constructors

        #region Private Destructors

        ~RenderText()
        {
            Dispose();
            // if (this.textSprite != null)
            //     this.textSprite = null;
        }

        #endregion Private Destructors

        #region Public Properties

        public string Message
        {
            get { return message; }
            set { message = value; }
        }

        public SharpDX.Color4 TextColor
        {
            get { return textColor; }
            set { textColor = value; }
        }

        #endregion Public Properties

        #region Public Methods

        public static void DrawString(string message, int positionX, int positionY, Color4 color, SharpDX.Direct3D11.Device device)
        {
            lock (device.ImmediateContext)
                RenderText.myTextBlockRenderer.DrawString(message, new SharpDX.Vector2(positionX, positionY), color);
        }

        /// <summary>
        /// Renders Text direct in 3d space by given coordinates.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="positionX"></param>
        /// <param name="positionY"></param>
        /// <param name="positionZ"></param>
        /// <param name="color4"></param>
        /// <param name="engine"></param>
        public static void DrawString(string message, Vector3 position, Color4 color4, Engine engine, int screenCoordinateOffsetX, int screenCoordinateOffsetY)
        {
            Size sizeOfViewport = new Size(engine.Grafic.viewPort.Width, engine.Grafic.viewPort.Height);
            var screenCoordinates = GeoMath.GetScreenCoordinates(position, sizeOfViewport, engine.GetWorldViewProjectionMatrix());

            RenderText.DrawString(message, screenCoordinates.X + screenCoordinateOffsetX, screenCoordinates.Y + screenCoordinateOffsetY, color4, engine.Grafic.Device);
        }

        public static void DrawString(string message, float positionX, float positionY, float positionZ, Color4 color4, Engine engine)
        {
            DrawString(message, new Vector3(positionX, positionY, positionZ), color4, engine, 0, 0);
        }

        public static void RenderFlush()
        {
            foreach (var item in RenderText.TextToRender)
            {
                item.queneForRendering = false;
                //
                //engine.DepthStateEnableZ(true);
                //RenderText.engine.SetFillmodeSolid();
                //RenderText.engine.BlendStateEnableAlpha(true);
                RenderText.myTextBlockRenderer.DrawString(item.message, new SharpDX.Vector2(item.posX, item.posY), item.textColor);
            }

            RenderText.TextToRender.Clear();
        }

        public void Dispose()
        {
            // this.textSprite.Dispose();
        }

        public void Render(int renderStep)
        {
            if (!queneForRendering)
                RenderText.TextToRender.Add(this);
            this.queneForRendering = true;
        }

        /// <summary>
        /// Renders Text on Screen
        /// </summary>
        /// <param name="message">message string</param>
        /// <param name="posX">Position X on Screen</param>
        /// <param name="posY">Position Y on Screen</param>
        /// <param name="textColor">Color of the Text</param>
        public void SetTextOnScreen(string message, int posX, int posY, Color4 textColor)
        {
            if (this.queneForRendering)
                Console.WriteLine("Textrenderer message can only changed one per Drawcall! \nNew Text: " + message);
            this.message = message;
            this.posX = posX;
            this.posY = posY;
            this.textColor = textColor;
        }

        #endregion Public Methods
    }
}